#include "usart.h"
#include "globalDevice.h"
#include "gd32f4xx_usart.h"
#include <stdio.h>
#include <string.h>

uart_manager_t uart_rx_manager = {0};
uart_manager_t uart_tx_manager = {0};
void usart0_init(void)
{
    uint32_t usart_periph = GPIOB;
    uint32_t usart_tx_pin = GPIO_PIN_6;
    uint32_t usart_rx_pin = GPIO_PIN_7;
    uint32_t usart_af = GPIO_AF_0;
    // 初始化发送管理结构
    memset(&uart_tx_manager, 0, sizeof(uart_tx_manager));
    nvic_irq_enable(USART0_IRQn, 0, 0);
    /* enable COM GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART0);

    // GPIO配置
    gpio_af_set(usart_periph, usart_af, usart_tx_pin);
    gpio_af_set(usart_periph, usart_af, usart_rx_pin);

    gpio_mode_set(usart_periph, GPIO_MODE_AF, GPIO_PUPD_PULLUP, usart_tx_pin);
    gpio_output_options_set(usart_periph, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usart_tx_pin);

    gpio_mode_set(usart_periph, GPIO_MODE_AF, GPIO_PUPD_PULLUP, usart_rx_pin);
    gpio_output_options_set(usart_periph, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usart_rx_pin);

    /* configure USART */
    usart_deinit(USART0);

    usart_word_length_set(USART0, USART_WL_8BIT);
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_baudrate_set(USART0, 115200U);
    usart_data_first_config(USART0, USART_MSBF_LSB);

    // 流控配置
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);

    // 使能接收和发送
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);

    // 使能DMA传输
    usart_dma_transmit_config(USART0, USART_TRANSMIT_DMA_ENABLE);
    usart_dma_receive_config(USART0, USART_RECEIVE_DMA_ENABLE);

    usart_flag_clear(USART0, USART_FLAG_IDLE);
    usart_interrupt_enable(USART0, USART_INT_IDLE);
    // 使能USART
    usart_enable(USART0);
}

/*!
    \brief      configure DMA for USART
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usart0_dma_config(void)
{
    /* 配置DMA接收 */
    dma_single_data_parameter_struct dma_init_struct;

    dma_deinit(DMA1, DMA_CH2);
    dma_single_data_para_struct_init(&dma_init_struct);

    dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
    dma_init_struct.memory0_addr = (uint32_t)uart_rx_manager.buf;
    dma_init_struct.number = BUFFER_SIZE;

    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    dma_init_struct.periph_addr = USART0_DATA_ADDRESS;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;

    dma_single_data_mode_init(DMA1, DMA_CH2, &dma_init_struct);
    dma_circulation_disable(DMA1, DMA_CH2);
    dma_channel_subperipheral_select(DMA1, DMA_CH2, DMA_SUBPERI4);

    /* 使能DMA传输完成中断 */
    dma_interrupt_enable(DMA1, DMA_CH2, DMA_CHXCTL_FTFIE);

    /* 启动DMA接收 */
    dma_channel_enable(DMA1, DMA_CH2);

    /* 配置DMA发送 */
    dma_single_data_parameter_struct dma_tx_init_struct;

    dma_deinit(DMA1, DMA_CH7); // USART0 TX使用DMA1 Channel 7
    dma_single_data_para_struct_init(&dma_tx_init_struct);

    /* 配置基本参数 */
    dma_tx_init_struct.direction = DMA_MEMORY_TO_PERIPH; // 内存到外设
    dma_tx_init_struct.memory0_addr = 0;                 // 发送时动态设置
    dma_tx_init_struct.number = 0;                       // 发送时动态设置

    /* 配置传输细节 */
    dma_tx_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_tx_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    dma_tx_init_struct.periph_addr = USART0_DATA_ADDRESS;
    dma_tx_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_tx_init_struct.priority = DMA_PRIORITY_MEDIUM; // 接收优先级更高

    /* 初始化DMA */
    dma_single_data_mode_init(DMA1, DMA_CH7, &dma_tx_init_struct);
    dma_circulation_disable(DMA1, DMA_CH7);
    dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4);

    /* 使能DMA发送完成中断 */
    dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
}

int dma_channel_enabled(uint32_t dma_periph, dma_channel_enum channelx)
{
    return (DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_CHEN);
}

/*!
    \brief      使用DMA发送数据
    \param[in]  data: 要发送的数据
    \param[in]  size: 数据大小
    \retval     1: 成功启动发送, 0: 失败(可能发送忙)
*/
uint8_t uart0_send_data(uint8_t *data, uint16_t size)
{
    /* 检查当前是否有发送正在进行 - 只检查通道状态 */
    if (dma_channel_enabled(DMA1, DMA_CH7))
    {
        return 0; // 发送忙
    }

    /* 清除所有标志 - 无论前一次传输状态如何，都确保清除 */
    dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_FTF);
    dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_HTF);
    dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_FEE);

    /* 配置DMA发送 */
    dma_channel_disable(DMA1, DMA_CH7); // 虽然通道已禁用，但为安全起见再次禁用

    /* 设置源地址和数据大小 */
    memcpy(uart_tx_manager.buf, data, size);
    dma_memory_address_config(DMA1, DMA_CH7, 0, (uint32_t)uart_tx_manager.buf);
    dma_transfer_number_config(DMA1, DMA_CH7, size);

    /* 启动发送 */
    dma_channel_enable(DMA1, DMA_CH7);

    return 1; // 成功启动发送
}